// ChSServer.cpp : implementation file
//

#include "stdafx.h"
#include "ChatServer.h"
#include "ChSServer.h"


// CChSServer
CChSServer* CChSServer::s_pInstance = NULL;

CChSServer::CChSServer()
{
	m_bStarted = FALSE;
}

CChSServer::~CChSServer()
{
}

CChSServer* CChSServer::Instance()
{
	if(NULL == s_pInstance)
		s_pInstance = new CChSServer;
	return s_pInstance;
}

BOOL CChSServer::Initialize()
{
	return NULL != Instance();
}

void CChSServer::Uninitialize()
{
	delete s_pInstance;
	s_pInstance = NULL;
}

BOOL CChSServer::Start(const CString& strHost, UINT uPort)
{
	if(TRUE == m_bStarted)
	{
		AfxMessageBox(_T("Server olready started"));
		return FALSE;
	}

	m_bStarted = TRUE;

	BOOL bRet = Create(uPort,SOCK_STREAM,
		FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
		strHost 
		);

	bRet = bRet & Listen();

	return bRet;
}

void CChSServer::Stop()
{
	SendToAll(_T("bye"));
	vector<CChSClientContext*>::iterator it = m_ClientsArr.begin();
	vector<CChSClientContext*>::iterator end = m_ClientsArr.end();
	while(it != end)
	{
		(*it)->ShutDown();
		(*it)->Close();
		delete (*it);

		++it;
	}

	m_ClientsArr.clear();

	Close();

	m_bStarted = FALSE;
}

void CChSServer::OnAccept(int nErrorCode)
{
	CChSClientContext *pClientContext = new CChSClientContext;
	if(TRUE == Accept(*pClientContext))
	{
		m_ClientsArr.push_back(pClientContext);
		AfxGetApp()->GetMainWnd()->SendMessage(CHSM_ACCEPT_NEW_CLIENT_GOOD,0,0);
	}
	else
	{
		AfxGetApp()->GetMainWnd()->SendMessage(CHSM_ACCEPT_NEW_CLIENT_FAIL,0,0);
	}
}

void CChSServer::SendToAll(const CString& strMessage)
{
	vector<CChSClientContext*> _removeArr;
	vector<CChSClientContext*>::const_iterator it = m_ClientsArr.begin();
	vector<CChSClientContext*>::const_iterator end = m_ClientsArr.end();
	while(it != end)
	{
		if(0 >= (*it)->Send((LPCTSTR)strMessage,(strMessage.GetLength()+1)*sizeof(TCHAR)))
		{
			_removeArr.push_back(*it);		
		}
		++it;
	}

}

BOOL CChSServer::SendToClientUsersList(CChSClientContext *pClientContext)
{
	vector<CChSClientContext*> _removeArr;
	vector<CChSClientContext*>::const_iterator it = m_ClientsArr.begin();
	vector<CChSClientContext*>::const_iterator end = m_ClientsArr.end();
	CString strUpdateMsg = NEW_USER_MESSAGE_PREFIX;
	CString strMsg = _T("");
	while(it != end)
	{
		strMsg = strUpdateMsg + (*it)->UserName(); 
		Sleep(200);
		if(0 >= pClientContext->Send((LPCTSTR)strMsg.GetString(),(strMsg.GetLength()+1)*sizeof(TCHAR)))
		{
			_removeArr.push_back(*it);	
		}
		++it;
	}

	return TRUE;
}

BOOL CChSServer::RemoveClient(const CChSClientContext *pClientContext)
{
	vector<CChSClientContext*>::iterator iter = find(m_ClientsArr.begin(),m_ClientsArr.end(),pClientContext);
	if(iter != m_ClientsArr.end())
	{
		m_ClientsArr.erase(iter);
		return TRUE;
	}

	return FALSE;
}

BOOL CChSServer::FindClient(const CString& strUserName)
{
	vector<CChSClientContext*>::const_iterator iter = m_ClientsArr.begin();
	vector<CChSClientContext*>::const_iterator end = m_ClientsArr.end();
	while(iter != end)
	{
		if((*iter)->UserName() == strUserName)
			return TRUE;
		++iter;
	}

	return FALSE;
}

void CChSServer::UpdateClientsList()
{
	CString strMessage = _T("test");
	vector<CChSClientContext*>::iterator it = m_ClientsArr.begin();
	while(it != m_ClientsArr.end())
	{
		if(0 >= (*it)->Send((LPCTSTR)strMessage,(strMessage.GetLength()+1)*sizeof(TCHAR)))
		{
			delete (*it);
			it = m_ClientsArr.erase(it);		
		}
		else
			++it;
	}
}

